package com.vshop.platform.system.crud.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.vshop.framework.core.exception.ServiceException;
import com.vshop.framework.core.util.MapstructUtil;
import com.vshop.framework.mybatisflex.page.PageData;
import com.vshop.framework.mybatisflex.page.PageQuery;
import com.vshop.framework.satoken.helper.LoginHelper;
import com.vshop.platform.system.crud.dao.SysRoleDao;
import com.vshop.platform.system.crud.dao.SysUserDao;
import com.vshop.platform.system.crud.dao.SysUserPostDao;
import com.vshop.platform.system.crud.dao.SysUserRoleDao;
import com.vshop.platform.system.domain.entity.SysUser;
import com.vshop.platform.system.domain.entity.SysUserRole;
import com.vshop.platform.system.domain.param.SysUserParam;
import com.vshop.platform.system.domain.vo.RoleCheckedVo;
import com.vshop.platform.system.domain.vo.SysRoleVo;
import com.vshop.platform.system.domain.vo.SysUserVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Slf4j
@RequiredArgsConstructor
@Service
public class SysUserService {
    private final DataScopeService dataScopeService;
    private final SysUserDao sysUserDao;
    private final SysUserRoleDao sysUserRoleDao;
    private final SysUserPostDao sysUserPostDao;
    private final SysRoleDao sysRoleDao;

    public PageData<SysUserVo> page(SysUserParam param, PageQuery pageQuery) {
        QueryWrapper queryWrapper = sysUserDao.buildQueryWrapper(param);
        Page<SysUserVo> page = sysUserDao.pageAs(pageQuery.build(), queryWrapper, SysUserVo.class);
        return PageData.build(page);
    }


    @Transactional
    public boolean save(SysUserParam param) {

        dataScopeService.checkDeptDataScope(param.getDeptId());
        if (sysUserDao.checkExistUserName(param)) {
            throw new ServiceException("新增用户'" + param.getUserName() + "'失败，登录账号已存在");
        }
        if (ObjectUtil.isNotEmpty(param.getPhoneNumber()) && sysUserDao.checkExistPhone(param)) {
            throw new ServiceException("新增用户'" + param.getUserName() + "'失败，手机号码已存在");
        }
        if (ObjectUtil.isNotEmpty(param.getEmail()) && sysUserDao.checkExistEmail(param)) {
            throw new ServiceException("新增用户'" + param.getUserName() + "'失败，邮箱账号已存在");
        }
//        if (!tenantService.checkAccountBalance(TenantHelper.getTenantId())) {
//            return R.fail("当前租户下用户名额不足，请您联系管理员增加租户用户数量！");
//        }

        SysUser entity = MapstructUtil.convert(param, SysUser.class);
        Assert.notNull(entity, "添加对象不能为空");
        entity.setPassword(BCrypt.hashpw(entity.getPassword()));
        boolean saveFlag = sysUserDao.save(entity);
        if (saveFlag) {
            // 新增用户岗位关联
            sysUserPostDao.saveUserPost(entity.getUserId(), param.getPostIds());
            // 新增用户与角色关联
            sysUserRoleDao.saveUserRole(entity.getUserId(), param.getRoleIds());
            return true;
        }
        return false;
    }

    @Transactional
    public boolean update(SysUserParam param) {
        Assert.notNull(param.getUserId(), "用户ID不能为空");

        Long userId = param.getUserId();
        this.checkUserAllowed(userId);
        dataScopeService.checkUserDataScope(userId);
        dataScopeService.checkDeptDataScope(param.getDeptId());
        if (sysUserDao.checkExistUserName(param)) {
            throw new ServiceException("修改用户'" + param.getUserName() + "'失败，登录账号已存在");
        }
        if (ObjectUtil.isNotEmpty(param.getPhoneNumber()) && sysUserDao.checkExistPhone(param)) {
            throw new ServiceException("修改用户'" + param.getUserName() + "'失败，手机号码已存在");
        }
        if (ObjectUtil.isNotEmpty(param.getEmail()) && sysUserDao.checkExistEmail(param)) {
            throw new ServiceException("修改用户'" + param.getUserName() + "'失败，邮箱账号已存在");
        }
        // 删除用户与岗位关联
        sysUserPostDao.removeUserPostByUserId(userId);
        // 新增用户与岗位关联
        sysUserPostDao.saveUserPost(userId, param.getPostIds());

        // 删除用户与角色关联
        sysUserRoleDao.removeUserRoleByUserId(userId);
        // 新增用户与角色关联
        sysUserRoleDao.saveUserRole(userId, param.getRoleIds());

        SysUser entity = MapstructUtil.convert(param, SysUser.class);
        return sysUserDao.updateById(entity);
    }

    public boolean removeByIds(List<Long> userIds) {

        if (CollUtil.contains(userIds, LoginHelper.getUserId())) {
            throw new ServiceException("选择用户包含自身，不能删除");
        }
        for (Long userId : userIds) {
            this.checkUserAllowed(userId);
            dataScopeService.checkUserDataScope(userId);
        }
        // 删除用户与岗位关联
        sysUserPostDao.removeUserPostByUserIds(userIds);
        // 删除用户与角色关联
        sysUserRoleDao.removeUserRoleByUserIds(userIds);

        //逻辑删除：UPDATE `sys_user` SET `del_flag` = 1 WHERE (`user_id` = 101810794781507584 ) AND `del_flag` = 0 AND `tenant_id` = 0
        return sysUserDao.removeByIds(userIds);
    }

    /**
     * 更改状态
     */
    public boolean changeStatus(Long userId, String status) {
        Assert.notNull(userId, "ID不能为空");
        return sysUserDao.changeStatus(userId, status);
    }


    public SysUserVo getInfoById(Long userId) {
        SysUser entity = sysUserDao.getById(userId);
        Assert.notNull(entity, "用户不存在");
        SysUserVo vo = MapstructUtil.convert(entity, SysUserVo.class);
        vo.setPostIds(sysUserPostDao.listPostIdByUserId(userId));
        vo.setRoleIds(sysUserRoleDao.listRoleIdByUserId(userId));
        return vo;
    }

    /**
     * 用户授权角色
     *
     * @param userId  用户ID
     * @param roleIds 角色组
     */
    @Transactional
    public void authRole(Long userId, List<Long> roleIds) {
        Assert.notNull(userId, "用户ID不能为空");
        Assert.notEmpty(roleIds, "授权角色不能为空");
        dataScopeService.checkUserDataScope(userId);
        sysUserRoleDao.removeUserRoleByUserId(userId);
        sysUserRoleDao.saveUserRole(userId, roleIds);
    }

    /**
     * 根据用户ID获取授权角色 和 查询角色集合
     */
    public RoleCheckedVo getAuthRole(Long userId) {
        List<SysRoleVo> roles = sysRoleDao.listAs(QueryWrapper.create(), SysRoleVo.class);
        List<Long> roleIds = sysUserRoleDao.listRoleIdByUserId(userId);
        RoleCheckedVo vo = new RoleCheckedVo();
        vo.setCheckedKeys(roleIds);
        vo.setList(roles);
        return vo;
    }

    /**
     * 校验用户是否允许操作
     *
     * @param userId 用户Id
     */
    private void checkUserAllowed(Long userId) {
        if (ObjectUtil.isNotNull(userId) && LoginHelper.isSuperAdmin(userId)) {
            throw new ServiceException("不允许操作超级管理员用户");
        }
    }
}
